package com.koron.car.web.carledger.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.koron.bean.query.OrderItem;
import com.koron.bean.system.staff.vo.EamUser;
import com.koron.car.config.Constants;
import com.koron.car.web.carledger.bean.query.CarQuery;
import com.koron.car.web.carledger.bean.vo.CarVO;
import com.koron.car.web.carledger.mapper.CarMapper;
import com.koron.car.web.carledger.service.CarService;
import com.koron.car.web.common.CommonUtils;
import com.koron.car.web.motorcade.service.MotorcadeService;
import com.koron.common.core.config.ThreadLocalContext;
import com.koron.common.core.util.CodeTools;
import com.koron.common.core.util.OrgCacheUtils;
import com.koron.common.core.util.qywx.QywxProperties;
import com.koron.common.core.util.weixin.WxProgramMessageUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;

@Slf4j
@Service
public class CarServiceImpl implements CarService {

    @Autowired
    private OrgCacheUtils orgCacheUtils;

    /**
     * 通过ID查询单条数据
     * @param id 主键
     * @return 实例对象
     */
    @Override
    @TaskAnnotation("queryById")
    public CarVO queryById(SessionFactory factory, String id) {
        CarMapper mapper = factory.getMapper(CarMapper.class);
        CarVO carVO = mapper.queryById(id);
        // 报废的前提条件：1、购车年限超过12年 2、车的总行驶距离超过30万公里
        carVO.setOwnerOrgName(orgCacheUtils.getOrgNameById(carVO.getOwnerOrg()));
        return carVO;
    }

    /**
     * 查询多条数据
     * @param car 查询条件
     * @return 对象列表
     */
    @Override
    @TaskAnnotation("queryList")
    public List<CarVO> queryList(SessionFactory factory, CarQuery car) {
        CarMapper mapper = factory.getMapper(CarMapper.class);
        car.setDeleteFlag(car.getDeleteFlag() == null ? false : car.getDeleteFlag());
        List<CarVO> carVOS = mapper.queryList(car);
        if (car.getOrderBy().contains("owner_org_name")){
            OrderItem order = car.getOrders().stream().filter(orderItem -> orderItem.getColumn().equals("`owner_org_name`")).findFirst().get();
            carVOS.stream().forEach(row -> row.setOwnerOrgName(orgCacheUtils.getOrgNameById(row.getOwnerOrg())));
            if (order.isAsc()) {
                carVOS.sort(Comparator.comparing(CarVO::getOwnerOrgName));
            }else {
                carVOS.sort(Comparator.comparing(CarVO::getOwnerOrgName).reversed());
            }
        }else {
            carVOS.stream().forEach(row -> row.setOwnerOrgName(orgCacheUtils.getOrgNameById(row.getOwnerOrg())));
        }
        return carVOS;
    }

    @Override
    @TaskAnnotation("schedulable")
    public List<CarVO> schedulable(SessionFactory factory, CarQuery query) {
        CarMapper mapper = factory.getMapper(CarMapper.class);
        query.setDeleteFlag(query.getDeleteFlag() == null ? false : query.getDeleteFlag());
        List<CarVO> carVOS = mapper.queryList(query);
        carVOS.stream().forEach(row -> row.setOwnerOrgName(orgCacheUtils.getOrgNameById(row.getOwnerOrg())));
        return carVOS;
    }

    /**
     * 新增数据
     * @param car 实例对象
     * @return 实例对象
     */
    @Override
    @TaskAnnotation("saveOrUpdate")
    public CarVO saveOrUpdate(SessionFactory factory, CarVO car) {
        CarMapper mapper = factory.getMapper(CarMapper.class);

        //如果车辆提交,要做判断。保存不做判断
        if(car.getSubmit()){
            //先查询车架号是否存在
            List<CarVO> carVOS1 = mapper.queryCheckOnly(car.getFrame(),null);
            if (!CollectionUtils.isEmpty(carVOS1)) {
                carVOS1.stream().forEach(row ->
                    Assert.isTrue(StringUtils.equalsIgnoreCase(car.getId(), row.getId()), "车架号已存在")
                );
            }
            //查看车牌号是不是存在(报废车辆不算入统计)
            List<CarVO> carVOS2 = mapper.queryCheckOnly(null,car.getLicPlateNum());
            if (!CollectionUtils.isEmpty(carVOS2)) {
                carVOS2.stream().forEach(row ->
                    Assert.isTrue(StringUtils.equalsIgnoreCase(car.getId(), row.getId()), "车牌号已存在")
                );
            }
        }
        if(StringUtils.isBlank(car.getId())) {
            // 累计行驶记录默认为0，每次申请完成时，更新该值
            car.setTotalDistance(0.0);
            // 年度行驶记录默认为0，每年清零，每次申请完成后，更新该值
            car.setYearDistance(0.0);
            car.setState(Constants.CarState.DRAFT);
        }
        // 初始化
        CommonUtils.update(car, ThreadLocalContext.getLoginUser());
        CommonUtils.update(car);
        EamUser eamUser = ThreadLocalContext.get();
        car.setDeptId(StringUtils.isBlank(car.getDeptId()) ? eamUser.getOrgId() : car.getDeptId());
        // 设置成未定编
        car.setId(StringUtils.isBlank(car.getId()) ? CodeTools.getCode32() : car.getId());
        if(car.getSubmit()) {
            car.setState(Constants.CarState.FREE);
        }
        mapper.saveOrUpdate(car);
        return car;
    }

    /**
     * 通过主键删除数据
     * @param id 主键
     * @return 是否成功
     */
    @Override
    @TaskAnnotation("deleteById")
    public Boolean deleteById(SessionFactory factory, String id) {
        CarMapper mapper = factory.getMapper(CarMapper.class);
        return mapper.deleteById(id) > 0;
    }

    /**
     * 通过主键删除数据
     * @param id 主键
     * @return 是否成功
     */
    @Override
    @TaskAnnotation("hiddenById")
    public Boolean hiddenById(SessionFactory factory, String id) {
        CarMapper mapper = factory.getMapper(CarMapper.class);
        return mapper.hiddenById(id) > 0;
    }

    /**
     * 由业务扭转导致状态变化
     * @param factory
     * @param carId
     * @param state
     * @return
     */
    @Override
    @TaskAnnotation("updateState")
    public synchronized Boolean updateState(SessionFactory factory, String carId, String state) {
        CarMapper mapper = factory.getMapper(CarMapper.class);
        CarVO carVO = mapper.queryById(carId);
        String oldState = carVO.getState();
        if(StringUtils.equals(oldState, state) && StringUtils.equals(state, Constants.CarState.OUTSITE)) {
            //
        }
        return mapper.updateState(carId, state) > 0;
    }

    /**
     * 至少有一个不为空，不为空时更新距离
     * @param factory
     * @param carId
     * @param currDistance 本单行驶距离
     * @param currTotalDistance 累计行驶距离
     * @return
     */
    @Override
    @TaskAnnotation("updateState")
    public Boolean updateDistance(SessionFactory factory, String carId, Double currDistance, Double currTotalDistance) {
        CarMapper mapper = factory.getMapper(CarMapper.class);
        if(StringUtils.isBlank(carId) || currTotalDistance == null) {
            return false;
        }
        CarVO carVO = mapper.queryById(carId);
        // 年度里程和累计里程，在新建时给了初始值，此处不用判空
        Double yearDistance = carVO.getYearDistance();
        yearDistance += currDistance;
        return mapper.updateDistance(carId, yearDistance, currTotalDistance) > 0;
    }

    @Override
    @TaskAnnotation("getBoundCar")
    public List<CarVO> getBoundCar(SessionFactory factory, CarQuery query) {
        CarMapper mapper = factory.getMapper(CarMapper.class);
        // 只查询未删除、未废弃，且可用的车辆
        query.setStates(Arrays.asList(Constants.CarState.FREE, Constants.CarState.OUTSITE,
                Constants.CarState.LEND, Constants.CarState.MAINTENANCE, Constants.CarState.MAINTAIN, Constants.CarState.RETENTION));
        query.setDeleteFlag(false);
        return mapper.getBoundCar(query);
    }

    @Override
    public int countCarByPrepareType(SessionFactory factory, String prepareType) {
        CarMapper mapper = factory.getMapper(CarMapper.class);
        return mapper.countCarByPrepareType(prepareType);
    }

    private RestTemplate template = new RestTemplate();

    @Autowired
    private QywxProperties qywxProperties;

    @Autowired
    private WxProgramMessageUtil wxProgramUtil;

    @Override
    public File createMiniProgramQRCode(String id, String name, String envVersion) {
        Map<String, Object> param = new HashMap<>();
        param.put("page", "pages/carManagement/carReady");
        param.put("scene", id);
        param.put("check_path", true);
        param.put("env_version", envVersion);
        // 请求路径url
        String token = wxProgramUtil.getAccessTokenCache();
        log.info("token = {}", token);
        String url = qywxProperties.getCodeUnLimit() + "?access_token=" + token;
        log.info("url = {}", url);
        // 请求体body
        HttpHeaders header = new HttpHeaders();
        header.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity requestEntity = new HttpEntity(param, header);
        ResponseEntity<byte[]> entity = template.exchange(url, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);
        HttpHeaders headers = entity.getHeaders();
        List<String> conentTypes = headers.get("Content-Type");
        StringBuilder sb = new StringBuilder();
        conentTypes.stream().forEach(contentType -> sb.append(contentType));
        Assert.isTrue(sb.toString().contains("image/jpeg"), "二维码生成失败");

        File file = new File("", StrUtil.format("{}_{}.jpg", id, name));
        FileUtil.writeBytes(entity.getBody(), file);

        return file;
    }
}
